/*
	Pulsar engine. Core.
	Additional include file. Standard events.

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.
		
	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

namespace pl
{

/// INewFrame interface
#define DECLARE_ON_NEW_FRAME() virtual void onNewFrame(pl_uint32 frameCounter)

/// INewFrame interface
class INewFrame : public ListNode<INewFrame>
{
public:
	/// Notify subscribers
	static bool callOnNewFrame();

	static pl_uint32 frameCounter;

protected:
	DECLARE_ON_NEW_FRAME() 
	{ 
		return; 
	}

	/// Ctor
	INewFrame();

private:
	/// Event collection
	static List<INewFrame> _newFrameGroup;
};

enum SignalInfo
{
	SIGNAL_INFO_CTRLC,
	SIGNAL_INFO_CTRLBREAK,
	SIGNAL_INFO_CLOSE,
	SIGNAL_INFO_LOGOFF,
	SIGNAL_INFO_SHUTDOWN,
	SIGNAL_INFO_UNKONWN
};

/// IAppEvents interface
#define DECLARE_ON_FATAL() virtual void onFatal(int exitCode, const pl_char* diags)
#define DECLARE_ON_EXCEPTION() virtual void onException(const pl::ExceptionInfo& info)
#define DECLARE_ON_SIGNAL() virtual HandleResult onSignal(pl::SignalInfo code)

class IAppEvents : public ListNode<IAppEvents>
{
public:
	static void callOnFatal(int exitCode, const pl_char* diags);
	static void callOnException(const pl::ExceptionInfo& info);
	static HandleResult callOnSignal(SignalInfo code);

protected:
	IAppEvents();

	DECLARE_ON_FATAL()
	{
	}
	DECLARE_ON_EXCEPTION()
	{
	}
	DECLARE_ON_SIGNAL()
	{
		return HANDLE_RESULT_NEXT;
	}

private:
	static List<IAppEvents> _appEventsGroup;
};

/// IAppDebug interface
#define DECLARE_ON_ASSERT() virtual HandleResult onAssert(const pl_char* file, pl_uint32 line, const pl_char* func, const pl_char* cond, const pl_char* msg, pl::AssertType type)
#define DECLARE_ON_THREAD() virtual void onThread(pl::ThreadEvent evt, const pl_char* threadName)
#define DECLARE_ON_MEMERR() virtual HandleResult onMemErr(const pl_char* file, pl_uint32 line, const pl_char* func, void* p, pl_int64 size, pl::MemoryError idEvent)

/**
	Thread events 
	Used with AppDebug system
*/
enum ThreadEvent
{
	/// New pl::Thread is started
	THREAD_EVENT_START,
	/// pl::Thread is finished
	THREAD_EVENT_END,
	/// New jod is started
	THREAD_EVENT_START_JOB,
	/// New jod is finished
	THREAD_EVENT_END_JOB,
	/// Can't destroy thread because job is still running
	THREAD_EVENT_CANT_DTOR
};

class IAppDebug : public ListNode<IAppDebug>
{
public:
	static HandleResult callOnAssert(const pl_char* file, pl_uint32 line, const pl_char* func, const pl_char* cond, const pl_char* msg, pl::AssertType type);
	static void callOnThread(pl::ThreadEvent evt, const pl_char* threadName);
	static HandleResult callOnMemErr(const pl_char* file, pl_uint32 line, const pl_char* func, void* p, pl_int64 size, pl::MemoryError idEvent);

protected:
	IAppDebug();

	DECLARE_ON_ASSERT()
	{
		return HANDLE_RESULT_NEXT;
	}
	DECLARE_ON_THREAD()
	{
		return;
	}
	DECLARE_ON_MEMERR()
	{
		return HANDLE_RESULT_NEXT;
	}

private:
	static List<IAppDebug> _appDebugGroup;
};

} // namespace pl

//
// End of file 'pulsar_events.h'
//
